package com.gitee.easyopen.support;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.gitee.easyopen.ApiConfig;
import com.gitee.easyopen.ApiInvoker;
import com.gitee.easyopen.Result;
import com.gitee.easyopen.register.AbstractInitializer;

/**
 * 提供API访问能力,新建一个类继承这个即可.RequestMapping中的value自己定义
 * 
 * <pre>
 * &#64;Controller
 * &#64;RequestMapping(value = "/api/v1")
 * public class IndexController extends ApiController {
 * }
 * 
 * 这样接口的统一访问路径为:http://ServerName:Port/contextPath/api/v1
 * </pre>
 */
public class ApiController extends AbstractInitializer implements ApplicationListener<ContextRefreshedEvent> {

    private volatile ApiInvoker invoker;
    private ApiConfig apiConfig;

    @RequestMapping(method = RequestMethod.POST)
    public void index(HttpServletRequest request, HttpServletResponse response) throws Throwable {
        // 调用接口方法,即调用被@Api标记的方法
        getInvoker().invoke(request, response);
    }

    // 捕捉异常
    @ExceptionHandler(value = Throwable.class)
    public void jsonErrorHandler(HttpServletRequest req, HttpServletResponse response, Throwable e) throws Exception {
        Result result = this.getInvoker().caugthException(e);
        this.getInvoker().responseResult(response, result);
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        this.apiConfig = this.getApiConfig();
        this.initApiConfig(this.apiConfig);
        this.init(event.getApplicationContext(), this.apiConfig);
    }

    public ApiInvoker getInvoker() {
        if (invoker == null) {
            synchronized (ApiInvoker.class) {
                if (invoker == null) {
                    invoker = new ApiInvoker(this.apiConfig);
                }
            }
        }
        return invoker;
    }

    protected void initApiConfig(ApiConfig apiConfig) {

    }

    protected ApiConfig getApiConfig() {
        return new ApiConfig();
    }

}
